
package com.hlkj.pay.gateway.order.impl;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.hlkj.framework.common.util.collection.CollectionUtils;
import com.hlkj.framework.extension.executor.ExtensionExecutor;
import com.hlkj.framework.extension.scenario.BizScenario;
import com.hlkj.pay.app.merchant.ext.ChannelMerchantSubsidyOrderExtPt;
import com.hlkj.pay.app.merchant.ext.dto.profit.ChannelSubsidyOrderContext;
import com.hlkj.pay.dto.order.PayOrderSubsidyDto;
import com.hlkj.pay.dto.order.SubsidyOrderResultDto;
import com.hlkj.pay.enums.PayEnums;
import com.hlkj.pay.enums.PayOrderEnums;
import com.hlkj.pay.gateway.order.IChannelSubsidyOrderGateway;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAppChannelDO;
import com.hlkj.pay.infrastructure.model.order.PayOrderDO;
import com.hlkj.pay.infrastructure.model.pay.PayChannelRequestDO;
import com.hlkj.pay.service.merchant.IMerchantApplicationService;
import com.hlkj.pay.service.pay.IPayChannelService;
import com.hlkj.pay.service.pay.IPayWayService;
import com.hlkj.pay.service.pay.IProviderService;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author HlpayTeam
 * @date 2025/01/06 17:38
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ChannelSubsidyOrderGatewayImpl implements IChannelSubsidyOrderGateway {

    @Value("${hlkj.pay.barrier:false}")
    private boolean barrier;

    @Value("${hlkj.pay.test:false}")
    private boolean test;

    @Value("${hlkj.domain}")
    private String domain;

    private final ExtensionExecutor extensionExecutor;

    private final IMerchantApplicationService merchantApplicationService;

    private final IProviderService providerService;

    private final IPayChannelService payChannelService;

    private final IPayWayService payWayService;

    @Override
    public boolean extensionExist(String channelCode) {
        return extensionExecutor.executeExist(ChannelMerchantSubsidyOrderExtPt.class, BizScenario.valueOf(channelCode));
    }

    @Override
    public SubsidyOrderResultDto submitSubsidyOrder(ChannelSubsidyOrderContext channelSubsidyOrderContext) {
        // 订单信息
        PayOrderDO payOrderDO = channelSubsidyOrderContext.getPayOrderDO();
        // 返回结果
        SubsidyOrderResultDto subsidyOrderResultDto = new SubsidyOrderResultDto();
        if(!extensionExist(payOrderDO.getChannelCode())){
            subsidyOrderResultDto.setRemark("通道未实现");
            return subsidyOrderResultDto;
        }
        // 商户通道信息
        MerchantAppChannelDO merchantAppChannelDO = merchantApplicationService.queryAppChannelDetail(payOrderDO.getMchChannelCode());
        channelSubsidyOrderContext.setMerchantAppChannelDO(merchantAppChannelDO);
        channelSubsidyOrderContext.setProviderChannelConfig(providerService.queryConfig(merchantAppChannelDO.getProviderCode(), merchantAppChannelDO.getChannelCode()));
        channelSubsidyOrderContext.setTest(test);
        channelSubsidyOrderContext.setPayWayDO(payWayService.queryByCode(payOrderDO.getPayWayCode()));
        extensionExecutor.executeVoid(ChannelMerchantSubsidyOrderExtPt.class, BizScenario.valueOf(merchantAppChannelDO.getChannelCode()),
                ex -> ex.submitOrderSubsidy(channelSubsidyOrderContext));
        PayChannelRequestDO payChannelRequestDO = channelSubsidyOrderContext.getPayChannelRequest();
        if (payChannelRequestDO != null) {
            payChannelRequestDO.setRelationId(channelSubsidyOrderContext.getSubsidyRequestId());
            payChannelRequestDO.setSn(payChannelRequestDO.getSn());
            payChannelRequestDO.setChannelCode(payOrderDO.getChannelCode());
            payChannelRequestDO.setProviderCode(payOrderDO.getProviderCode());
            payChannelService.saveRequest(payChannelRequestDO, PayEnums.CHANNEL_REQUEST_TYPE.SUBSIDY_ORDER);
        }
        if (!channelSubsidyOrderContext.isProcessStatus()) {
            subsidyOrderResultDto.setPayOrderSubsidyStatus(PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS.FAIL);
            subsidyOrderResultDto.setRemark(channelSubsidyOrderContext.getRemark());
        }else {
            List<PayOrderSubsidyDto> failPayOrderSubsidyList = channelSubsidyOrderContext.getPayOrderSubsidyDtoList().stream()
                    .filter(payOrderSubsidyDto -> PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS.FAIL.getCode().equals(payOrderSubsidyDto.getStatus().getCode())).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(failPayOrderSubsidyList)) {
                subsidyOrderResultDto.setPayOrderSubsidyStatus(PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS.PROCESSING);
            }
            else {
                if (failPayOrderSubsidyList.size() == failPayOrderSubsidyList.size()) {
                    subsidyOrderResultDto.setPayOrderSubsidyStatus(PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS.FAIL);
                    subsidyOrderResultDto.setRemark(failPayOrderSubsidyList.get(0).getFailReason());
                }
                else {
                    subsidyOrderResultDto.setPayOrderSubsidyStatus(PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS.PROCESSING);
                }
            }
        }
        return subsidyOrderResultDto;
    }

    @Override
    public SubsidyOrderResultDto querySubsidyOrder(ChannelSubsidyOrderContext channelSubsidyOrderContext) {
        // 订单信息
        PayOrderDO payOrderDO = channelSubsidyOrderContext.getPayOrderDO();
        // 返回结果
        SubsidyOrderResultDto subsidyOrderResultDto = new SubsidyOrderResultDto();
        if(!extensionExist(payOrderDO.getChannelCode())){
            subsidyOrderResultDto.setRemark("通道未实现");
            return subsidyOrderResultDto;
        }
        // 商户通道信息
        MerchantAppChannelDO merchantAppChannelDO = merchantApplicationService.queryAppChannelDetail(payOrderDO.getMchChannelCode());
        channelSubsidyOrderContext.setMerchantAppChannelDO(merchantAppChannelDO);
        channelSubsidyOrderContext.setProviderChannelConfig(providerService.queryConfig(merchantAppChannelDO.getProviderCode(), merchantAppChannelDO.getChannelCode()));
        channelSubsidyOrderContext.setTest(test);
        channelSubsidyOrderContext.setPayWayDO(payWayService.queryByCode(payOrderDO.getPayWayCode()));
        extensionExecutor.executeVoid(ChannelMerchantSubsidyOrderExtPt.class, BizScenario.valueOf(merchantAppChannelDO.getChannelCode()),
                ex -> ex.queryOrderSubsidy(channelSubsidyOrderContext));
        subsidyOrderResultDto.setPayOrderSubsidyList(channelSubsidyOrderContext.getOrderSubsidyDetailList());
        PayChannelRequestDO payChannelRequestDO = channelSubsidyOrderContext.getPayChannelRequest();
        if (payChannelRequestDO != null) {
            payChannelRequestDO.setRelationId(channelSubsidyOrderContext.getSubsidyRequestId());
            payChannelRequestDO.setSn(payChannelRequestDO.getSn());
            payChannelRequestDO.setChannelCode(payOrderDO.getChannelCode());
            payChannelRequestDO.setProviderCode(payOrderDO.getProviderCode());
            payChannelService.saveRequest(payChannelRequestDO, PayEnums.CHANNEL_REQUEST_TYPE.SUBSIDY_ORDER);
        }
        if (!channelSubsidyOrderContext.isProcessStatus()) {
            subsidyOrderResultDto.setPayOrderSubsidyStatus(PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS.FAIL);
            subsidyOrderResultDto.setRemark(channelSubsidyOrderContext.getRemark());
        }
        return subsidyOrderResultDto;
    }

    @Override
    public SubsidyOrderResultDto submitSubsidyRefundOrder(ChannelSubsidyOrderContext channelSubsidyOrderContext) {
        // 订单信息
        PayOrderDO payOrderDO = channelSubsidyOrderContext.getPayOrderDO();
        // 返回结果
        SubsidyOrderResultDto subsidyOrderResultDto = new SubsidyOrderResultDto();
        if(!extensionExist(payOrderDO.getChannelCode())){
            subsidyOrderResultDto.setRemark("通道未实现");
            return subsidyOrderResultDto;
        }
        // 商户通道信息
        MerchantAppChannelDO merchantAppChannelDO = merchantApplicationService.queryAppChannelDetail(payOrderDO.getMchChannelCode());
        channelSubsidyOrderContext.setMerchantAppChannelDO(merchantAppChannelDO);
        channelSubsidyOrderContext.setProviderChannelConfig(providerService.queryConfig(merchantAppChannelDO.getProviderCode(), merchantAppChannelDO.getChannelCode()));
        channelSubsidyOrderContext.setTest(test);
        channelSubsidyOrderContext.setPayWayDO(payWayService.queryByCode(payOrderDO.getPayWayCode()));
        extensionExecutor.executeVoid(ChannelMerchantSubsidyOrderExtPt.class, BizScenario.valueOf(merchantAppChannelDO.getChannelCode()),
                ex -> ex.submitRefundOrderSubsidy(channelSubsidyOrderContext));
        channelSubsidyOrderContext.setRefundOrderSubsidyDtoList(channelSubsidyOrderContext.getRefundOrderSubsidyDtoList());
        PayChannelRequestDO payChannelRequestDO = channelSubsidyOrderContext.getPayChannelRequest();
        if (payChannelRequestDO != null) {
            payChannelRequestDO.setRelationId(channelSubsidyOrderContext.getSubsidyRequestId());
            payChannelRequestDO.setSn(payChannelRequestDO.getSn());
            payChannelRequestDO.setChannelCode(payOrderDO.getChannelCode());
            payChannelRequestDO.setProviderCode(payOrderDO.getProviderCode());
            payChannelService.saveRequest(payChannelRequestDO, PayEnums.CHANNEL_REQUEST_TYPE.SUBSIDY_ORDER);
        }
        if (!channelSubsidyOrderContext.isProcessStatus()) {
            subsidyOrderResultDto.setPayOrderSubsidyStatus(PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS.FAIL);
            subsidyOrderResultDto.setRemark(channelSubsidyOrderContext.getRemark());
        }else {
            List<PayOrderSubsidyDto> failPayOrderSubsidyList = channelSubsidyOrderContext.getRefundOrderSubsidyDtoList().stream()
                    .filter(payOrderSubsidyDto -> PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS.FAIL.getCode().equals(payOrderSubsidyDto.getStatus().getCode())).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(failPayOrderSubsidyList)) {
                subsidyOrderResultDto.setPayOrderSubsidyStatus(PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS.PROCESSING);
            }
            else {
                if (failPayOrderSubsidyList.size() == failPayOrderSubsidyList.size()) {
                    subsidyOrderResultDto.setPayOrderSubsidyStatus(PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS.FAIL);
                }
                else {
                    subsidyOrderResultDto.setPayOrderSubsidyStatus(PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS.PROCESSING);
                }
            }
        }
        return subsidyOrderResultDto;
    }

    @Override
    public SubsidyOrderResultDto querySubsidyRefundOrder(ChannelSubsidyOrderContext channelSubsidyOrderContext) {
        // 订单信息
        PayOrderDO payOrderDO = channelSubsidyOrderContext.getPayOrderDO();
        // 返回结果
        SubsidyOrderResultDto subsidyOrderResultDto = new SubsidyOrderResultDto();
        if(!extensionExist(payOrderDO.getChannelCode())){
            subsidyOrderResultDto.setRemark("通道未实现");
            return subsidyOrderResultDto;
        }
        // 商户通道信息
        MerchantAppChannelDO merchantAppChannelDO = merchantApplicationService.queryAppChannelDetail(payOrderDO.getMchChannelCode());
        channelSubsidyOrderContext.setMerchantAppChannelDO(merchantAppChannelDO);
        channelSubsidyOrderContext.setProviderChannelConfig(providerService.queryConfig(merchantAppChannelDO.getProviderCode(), merchantAppChannelDO.getChannelCode()));
        channelSubsidyOrderContext.setTest(test);
        channelSubsidyOrderContext.setPayWayDO(payWayService.queryByCode(payOrderDO.getPayWayCode()));
        extensionExecutor.executeVoid(ChannelMerchantSubsidyOrderExtPt.class, BizScenario.valueOf(merchantAppChannelDO.getChannelCode()),
                ex -> ex.queryRefundOrderSubsidy(channelSubsidyOrderContext));
        subsidyOrderResultDto.setPayOrderSubsidyList(channelSubsidyOrderContext.getOrderSubsidyDetailList());

        PayChannelRequestDO payChannelRequestDO = channelSubsidyOrderContext.getPayChannelRequest();
        if (payChannelRequestDO != null) {
            payChannelRequestDO.setRelationId(channelSubsidyOrderContext.getSubsidyRequestId());
            payChannelRequestDO.setSn(payChannelRequestDO.getSn());
            payChannelRequestDO.setChannelCode(payOrderDO.getChannelCode());
            payChannelRequestDO.setProviderCode(payOrderDO.getProviderCode());
            payChannelService.saveRequest(payChannelRequestDO, PayEnums.CHANNEL_REQUEST_TYPE.SUBSIDY_ORDER);
        }
        if (!channelSubsidyOrderContext.isProcessStatus()) {
            subsidyOrderResultDto.setPayOrderSubsidyStatus(PayOrderEnums.PAY_ORDER_SUBSIDY_STATUS.FAIL);
            subsidyOrderResultDto.setRemark(channelSubsidyOrderContext.getRemark());
        }
        return subsidyOrderResultDto;
    }

}
